package com.gzhryc.shared_device.cdcz.code.services;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.DateTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.pay.adaptation.weixin.WXPayNormalPayService;
import com.gzhryc.pay.adaptation.weixin.enums.EWXPayNormalRefundState;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalRefundResponse;
import com.gzhryc.shared_device.base.IMemberWalletService;
import com.gzhryc.shared_device.base.IPayServiceFactory;
import com.gzhryc.shared_device.base.enums.EPayType;
import com.gzhryc.shared_device.cdcz.core.CDCZConstants;
import com.gzhryc.shared_device.cdcz.core.models.CDCZExecuteResult;
import com.gzhryc.shared_device.common.payment.services.WXPayOrderService;
import com.gzhryc.shared_device.iot.core.NetworkDeviceWorkThreadPool;
import com.gzhryc.shared_device.base.enums.ELogState;
import com.gzhryc.shared_device.base.enums.EOrderOperateState;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.base.models.OrderLogContent;
import com.gzhryc.shared_device.cdcz.code.CDCZWorkThread;
import com.gzhryc.shared_device.cdcz.code.dao.CDCZOrderDao;
import com.gzhryc.shared_device.cdcz.code.dao.db.*;
import com.gzhryc.shared_device.cdcz.code.dao.enums.CDCZOrderEnum;
import com.gzhryc.shared_device.cdcz.code.dao.models.CDCZOrderDeviceLogContent;
import com.gzhryc.shared_device.cdcz.code.services.dto.CDCZOrderSearch;
import com.gzhryc.shared_device.cdcz.core.ICDCZNetworkService;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayOrder;
import com.gzhryc.shared_device.common.payment.dao.db.WXRefundOrder;
import com.gzhryc.shared_device.common.payment.services.WXRefundOrderService;
import org.apache.commons.lang3.time.DateUtils;

import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CDCZOrderService {

    static Logger log = Logger.getLogger(CDCZOrderService.class);

    public static CDCZOrderService self(Date date) {
        return MultiDBTools.getService(CDCZOrderService.class, date);
    }

    public static CDCZOrderService self(String jdbcKey,Date date) {
        return MultiDBTools.getService(jdbcKey, CDCZOrderService.class, date);
    }

    CDCZOrderDao dao;

    public CDCZOrderService(String jdbcKey,Date date) {
        dao = new CDCZOrderDao(jdbcKey,date);
    }

    public List<CDCZOrder> findBySearch(CDCZOrderSearch search, Integer pageNo, Integer pageLimit){
        Conditions conditions = dao.buildConditions(search);
        conditions.and().ge("createDate",search.getStartDate());
        conditions.and().le("createDate",search.getEndDate());
        conditions.and().in("placeId",search.getPlaceIds());
        conditions.desc("createDate");
        try {
            return dao.findByCondition(conditions,pageNo,pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public List<CDCZOrder> findWorkingByDeviceKeys(String chargeSocketSn, Integer slotNum){
        Conditions conditions = new Conditions(CDCZOrder.class);
        conditions.and().is("chargeSocketSn",chargeSocketSn);
        conditions.and().is("slotNum",slotNum);
        conditions.and().is("state", CDCZOrderEnum.State.Working.index());
        conditions.desc("createDate");

        try {
            return dao.findByCondition(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }

        return null;
    }

    public Long countBySearch(CDCZOrderSearch search){
        Conditions conditions = dao.buildConditions(search);
        conditions.and().ge("createDate",search.getStartDate());
        conditions.and().le("createDate",search.getEndDate());
        conditions.and().in("placeId",search.getPlaceIds());
        try {
            return dao.count(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return 0L;
    }

    public CDCZOrder getByTradeNo(String tradeNo){
        if(StringTools.isNotBlank(tradeNo)){
            try {
                return dao.getById(tradeNo);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return null;
    }

    public CDCZOrder getNewOpeningByDevice(String chargeSocketSn, Integer slotNum) {
        if (StringTools.isNotBlank(chargeSocketSn) && slotNum != null) {
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("chargeSocketSn", chargeSocketSn);
            conditions.and().is("slotNum", slotNum);
            conditions.and().is("state", CDCZOrderEnum.State.Opening.index());
            conditions.desc("createDate");
            try {
                return dao.get(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public CDCZOrder getNewWorkingByDevice(String chargeSocketSn, Integer slotNum) {
        if (StringTools.isNotBlank(chargeSocketSn) && slotNum != null) {
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("chargeSocketSn", chargeSocketSn);
            conditions.and().is("slotNum", slotNum);
            conditions.and().is("state", CDCZOrderEnum.State.Working.index());
            conditions.desc("createDate");
            try {
                return dao.get(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public boolean waitStartToOpening(String tradeNo,String chargeSocketSn,Integer slotNum){
        if(StringTools.isNotBlank(tradeNo)){
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo",tradeNo);
            conditions.and().is("state", CDCZOrderEnum.State.WaitStart.index());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setState(CDCZOrderEnum.State.Opening.index());
            updateEntity.setStartDate(new Date());

            JdbcSession.begin();
            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    //卡槽设置为忙碌
                    if(ChargeSocketSlotService.self().freeToWorking(chargeSocketSn,slotNum,tradeNo)){
                        JdbcSession.commit();
                        return true;
                    }
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }finally {
                JdbcSession.end();
            }
        }
        return false;
    }

    public boolean openingToWorking(CDCZOrder deviceOrder){
        if(deviceOrder != null && StringTools.isNotBlank(deviceOrder.getTradeNo())){
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo",deviceOrder.getTradeNo());
            conditions.and().is("state", CDCZOrderEnum.State.Opening.index());

            Date endDate = DateUtils.addMinutes(deviceOrder.getCreateDate(),deviceOrder.getMaxUseTimes());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setState(CDCZOrderEnum.State.Working.index());
            updateEntity.setEndDate(endDate);
            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    deviceOrder.setState(updateEntity.getState());
                    deviceOrder.setEndDate(endDate);
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean openingFail(CDCZOrder deviceOrder, OperateInfo operateInfo){
        if(StringTools.isNotBlank(deviceOrder.getTradeNo())){
            boolean flag = false;
            String errorMsg = null;
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo",deviceOrder.getTradeNo());
            conditions.and().is("state", CDCZOrderEnum.State.Opening.index());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setState(CDCZOrderEnum.State.Fail.index());

            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    ChargeSocketSlotService.self().toFree(deviceOrder.getChargeSocketSn(),deviceOrder.getSlotNum());
                    flag = true;
                }else{
                    errorMsg = "修改订单失败";
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
                errorMsg = e.getMessage();
            }

            if(flag){
                //增加日志
                CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder,operateInfo, ELogState.Success.index(),null);
            }else{
                CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder,operateInfo,ELogState.Fail.index(),errorMsg);
            }
        }
        return false;
    }

    public boolean updateAgentIdByPlaceId(Long placeId,Long agentId){
        if(placeId != null){
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("placeId",placeId);

            Map<String,Object> map = new HashMap<>();
            map.put("agentId",agentId);

            try {
                return dao.update(map,conditions) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean paySuccess(CDCZOrder deviceOrder, OrderLogContent logContent, ICDCZNetworkService networkService, OperateInfo operateInfo){
        String errorMsg  = null;
        boolean flag = false;
        try {
            flag = dao.insert(deviceOrder) > 0;
            if(!flag){
                errorMsg = "入库返回失败";
            }
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
            errorMsg = e.getMessage();
        }
        //增加日志
        if(StringTools.isBlank(operateInfo.getOperateNote())){
            operateInfo.setOperateNote("订单支付成功入库");
        }

        if(flag){
            CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder,logContent,operateInfo,ELogState.Success.index(),null);
            CDCZWorkThread workThread = new CDCZWorkThread(dao.getJdbcKey(),deviceOrder,networkService,operateInfo);
            NetworkDeviceWorkThreadPool.self().execute(workThread);
            return true;
        }else{
            log.error("新增充电插座订单失败，未触发充电命令，订单信息：{{0:json}}",deviceOrder);
           CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder,logContent,operateInfo,ELogState.Fail.index(),errorMsg);
        }
        return false;
    }

    /**
     * 退款成功
     * @param refundOrder
     * @param operateInfo
     * @return
     */
    public int refundSuccess(WXRefundOrder refundOrder,OperateInfo operateInfo){
        CDCZOrder deviceOrder = getByTradeNo(refundOrder.getBusinessTradeNo());
        if(deviceOrder == null){
            log.error("退款成功，未找到设备订单，退款订单信息：{{0:json}}",refundOrder);
            return -1;
        }

        int result = -1;
        if(EOrderOperateState.Cancelling.index().equals(deviceOrder.getOperateState())){
            //撤销订单
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo",refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState",EOrderOperateState.Cancelling.index());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setPayState(CDCZOrderEnum.PayState.Cancel.index());
            updateEntity.setPayMoney(deviceOrder.getPayMoney() - refundOrder.getRefundMoney());
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());
            if(CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState()) || CDCZOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                    || CDCZOrderEnum.State.Opening.index().equals(deviceOrder.getState())){
                updateEntity.setState(CDCZOrderEnum.State.Close.index());
            }
            if (CDCZOrderEnum.StopMode.Unknown.index().equals(deviceOrder.getStopMode())) {
                updateEntity.setStopMode(CDCZOrderEnum.StopMode.ForceStop.index());
            }
            updateEntity.setCancelDate(new Date());
            if(deviceOrder.getFinishDate() == null){
                updateEntity.setFinishDate(new Date());     //未完成时撤销
            }

            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    result = 1;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }else if(EOrderOperateState.Refunding.index().equals(deviceOrder.getOperateState())){
            //部分退款
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo",refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState",EOrderOperateState.Refunding.index());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setPayMoney(deviceOrder.getPayMoney() - refundOrder.getRefundMoney());
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());
            if (CDCZOrderEnum.StopMode.Unknown.index().equals(deviceOrder.getStopMode())) {
                updateEntity.setStopMode(CDCZOrderEnum.StopMode.ForceStop.index());
            }
            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    result = 2;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }else if(EOrderOperateState.Finishing.index().equals(deviceOrder.getOperateState())){
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo",refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState",EOrderOperateState.Finishing.index());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setPayMoney(deviceOrder.getPayMoney() - refundOrder.getRefundMoney());
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());
            if(CDCZOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                    || CDCZOrderEnum.State.Opening.index().equals(deviceOrder.getState())){
                updateEntity.setState(CDCZOrderEnum.State.Close.index());
            }else if(CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())){
                updateEntity.setState(CDCZOrderEnum.State.Finish.index());
            }
            if (CDCZOrderEnum.StopMode.Unknown.index().equals(deviceOrder.getStopMode())) {
                updateEntity.setStopMode(CDCZOrderEnum.StopMode.ForceStop.index());
            }
            updateEntity.setFinishDate(new Date());

            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    result = 3;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return result;
    }

    /**
     * 退款失败
     * @param refundOrder
     * @param operateInfo
     * @return
     */
    public boolean refundFail(WXRefundOrder refundOrder,OperateInfo operateInfo){
        CDCZOrder deviceOrder = getByTradeNo(refundOrder.getBusinessTradeNo());
        if(deviceOrder == null){
            log.error("退款成功，未找到设备订单，退款订单信息：{{0:json}}",refundOrder);
        }

        if(EOrderOperateState.Cancelling.index().equals(deviceOrder.getOperateState())){
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo",refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState",EOrderOperateState.Cancelling.index());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());
            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }else if(EOrderOperateState.Refunding.index().equals(deviceOrder.getOperateState())) {
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo", refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState", EOrderOperateState.Refunding.index());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());
            try {
                if (dao.updateNotNull(updateEntity, conditions) > 0) {
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }

    public boolean finishCharge(CDCZOrder deviceOrder,Long payMoney,Long walletMoney,Integer stopMode, Double useChargeElectricity){
        if(deviceOrder != null && StringTools.isNotBlank(deviceOrder.getTradeNo())) {
            Date endDate = new Date();
            Long chargeTime = DateTools.differenceMinute(deviceOrder.getStartDate(),endDate);

            if(useChargeElectricity == null || useChargeElectricity == 0) {
            	//本地计算充电量
            	if(deviceOrder.getMaxUsePower() != null && chargeTime > 0) {
            		//转换小时
            		Double hour = NumberTools.divide(chargeTime, 60, 2);
            		//计算电量 = 功率 * 小时 / 1000
            		useChargeElectricity = NumberTools.divide(NumberTools.multiply(deviceOrder.getMaxUsePower(),hour),1000,3);
            	}
            }
            
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("state", CDCZOrderEnum.State.Working.index());
            conditions.and().is("lastDeductionDate",deviceOrder.getLastDeductionDate());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setState(CDCZOrderEnum.State.Finish.index());
            updateEntity.setUseChargeElectricity(useChargeElectricity);
            updateEntity.setMaxPayMoney(payMoney);
            updateEntity.setMoney(walletMoney);
            updateEntity.setWalletMoney(walletMoney);
            updateEntity.setStopMode(stopMode);
            updateEntity.setEndDate(endDate);
            updateEntity.setUseTimes(chargeTime.intValue());
            updateEntity.setFinishDate(new Date());

            boolean flag = false;
            try {
                if (dao.updateNotNullAndInc(updateEntity, conditions, "money", "walletMoney") > 0) {
                    flag = true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
            //记录充电功率
            pullSlotInstantLog(deviceOrder);
            return flag;
        }
        return false;
    }

    /**
     * 时时收费，15分钟定时收费
     * @return
     */
    public boolean addUseMoney(CDCZOrder deviceOrder, Long maxPayMoney, Long walletMoney,Date lastDeductionDate) {
        if (StringTools.isNotBlank(deviceOrder.getTradeNo())) {
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo",deviceOrder.getTradeNo());
            conditions.and().is("state",CDCZOrderEnum.State.Working.index());
            conditions.and().is("lastDeductionDate",deviceOrder.getLastDeductionDate());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setMaxPayMoney(maxPayMoney);
            updateEntity.setMoney(walletMoney);
            updateEntity.setWalletMoney(walletMoney);
            updateEntity.setLastDeductionDate(lastDeductionDate);
            updateEntity.setUseTimes((int)DateTools.differenceMinute(deviceOrder.getStartDate(),lastDeductionDate));

            boolean flag = false;
            try {
                flag = dao.updateNotNullAndInc(updateEntity,conditions,"money","walletMoney") > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }

            pullSlotInstantLog(deviceOrder);

            if(flag) {
                return true;
            }
        }
        return false;
    }

    public boolean updateMaxUsePower(String tradeNo,Double maxUsePower){
        if (StringTools.isNotBlank(tradeNo) && maxUsePower != null) {
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo", tradeNo);

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setMaxUsePower(maxUsePower);

            try {
                return dao.updateNotNull(updateEntity, conditions) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }

    public int refund(CDCZOrder deviceOrder,Integer refundMoney,IPayServiceFactory payServiceFactory,OperateInfo operateInfo) throws LogicException{
        if (!CDCZOrderEnum.PayState.Success.index().equals(deviceOrder.getPayState())) {
            throw new LogicException("支付未成功");
        }
        if (!CDCZOrderEnum.State.Finish.index().equals(deviceOrder.getState())) {
            throw new LogicException("充电插座订单未完成，无法退款");
        }

        if(EPayType.WXPay.index().equals(deviceOrder.getPayType())){
            WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
            if (payOrder == null) {
                throw new LogicException("未找到本地微信支付订单");
            }
            WXPayNormalPayService payService = payServiceFactory.getWXPayNormalPayService(payOrder.getAppId(), CDCZConstants.BusinessType);
            if (payService == null) {
                throw new LogicException("未找到微信支付服务");
            }
            return refund(deviceOrder,payOrder,refundMoney,payService,operateInfo);
        }else if(EPayType.EWallet.index().equals(deviceOrder.getPayType())){
            return refund(deviceOrder,payServiceFactory.getMemberWalletService(),refundMoney,operateInfo);
        }
        return -1;
    }

    private int refund(CDCZOrder deviceOrder, WXPayOrder payOrder, Integer refundMoney, WXPayNormalPayService payService, OperateInfo operateInfo) throws LogicException {
        if (EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            if (deviceOrder.getPayMoney() < refundMoney) {
                throw new LogicException("没有足够的支付金额进行退款");
            }
            Integer payMoney = deviceOrder.getPayMoney() - refundMoney;
            if (payMoney <= 0) {
                throw new LogicException("退款金额超界");
            }

            Integer logState = ELogState.Success.index();
            String errorMsg = null;

            if (noOperateTo(deviceOrder.getTradeNo(), EOrderOperateState.Refunding.index())) {
                try {
                    //触发退款
                    WXRefundOrder refundOrder = WXRefundOrderService.self(deviceOrder.getCreateDate()).createRefundOrder(payOrder, refundMoney, operateInfo.getOperateNote());
                    WXPayNormalRefundResponse externalResult = payService.applyRefundOrder(refundOrder);
                    if (externalResult != null) {
                        if(StringTools.isNotBlank(externalResult.getCode()) && StringTools.isNotBlank(externalResult.getMessage())){
                            logState = ELogState.Fail.index();
                            errorMsg = externalResult.getMessage();
                        }else if (EWXPayNormalRefundState.SUCCESS.name().equals(externalResult.getStatus())){
                            log.info("{{0}}订单微信直接退款成功，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                        }else if(EWXPayNormalRefundState.CLOSED.name().equals(externalResult.getStatus()) ||
                                EWXPayNormalRefundState.ABNORMAL.name().equals(externalResult.getStatus())) {
                            logState = ELogState.Fail.index();
                            errorMsg = "退款订单已关闭或异常";
                            log.error("{{0}}订单微信退款失败，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                        }
                    } else {
                        logState = ELogState.Fail.index();
                        errorMsg = "微信退款失败，无响应";
                        log.error("{{0}}订单微信退款失败，无返回信息", payOrder.getTradeNo());
                    }
                } catch (Exception e) {
                    logState = ELogState.Fail.index();
                    errorMsg = e.getMessage();
                    log.error(e.getMessage(), e);
                } finally {
                    if (ELogState.Fail.index().equals(logState)) {
                        faceOperateState(deviceOrder.getTradeNo(), EOrderOperateState.NoOperation.index());
                    }
                }
            } else {
                logState = ELogState.Fail.index();
                errorMsg = "退款时锁定订单失败";
            }

            //增加日志
            CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, logState, errorMsg);
            if (ELogState.Success.index().equals(logState)) {
                return 1;
            }
        }
        return -1;
    }

    private int refund(CDCZOrder deviceOrder, IMemberWalletService memberWalletService,Integer refundMoney, OperateInfo operateInfo) throws LogicException {
        if (EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            Long refundMoneyLi = NumberTools.changeMoneyLi(NumberTools.changeMoney(refundMoney));
            if (deviceOrder.getWalletMoney() < refundMoneyLi) {
                throw new LogicException("没有足够的支付金额进行退款");
            }
            Long payMoneyLi = deviceOrder.getWalletMoney() - refundMoneyLi;
            if (payMoneyLi <= 0) {
                throw new LogicException("退款金额超界");
            }
            Long money = deviceOrder.getMoney() - refundMoneyLi;

            Integer operateState = ELogState.Success.index();
            String errorMsg = null;

            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("operateState", EOrderOperateState.NoOperation.index());
            conditions.and().is("state", deviceOrder.getState());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setWalletMoney(payMoneyLi);
            updateEntity.setMoney(money);

            JdbcSession.begin();
            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0) {
                    //触发退款
                    if (memberWalletService.addMoney(deviceOrder.getMemberId(), refundMoneyLi, operateInfo)) {
                        JdbcSession.commit();
                    } else {
                        operateState = ELogState.Fail.index();
                        errorMsg = "增加会员钱包" + NumberTools.getMoneyStr(refundMoney) + "元失败";
                    }
                }else{
                    operateState = ELogState.Fail.index();
                    errorMsg = "修改订单金额失败";
                }
            } catch (Exception e) {
                operateState = ELogState.Fail.index();
                errorMsg = e.getMessage();
                log.error(e.getMessage(), e);
            }finally {
                JdbcSession.end();
            }

            //增加日志
            CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
            if (ELogState.Success.index().equals(operateState)) {
                return 1;
            }
        }
        return -1;
    }

    public int cancel(CDCZOrder deviceOrder,IPayServiceFactory payServiceFactory, ICDCZNetworkService networkService, OperateInfo operateInfo) throws LogicException {
        if (CDCZOrderEnum.PayState.Cancel.index().equals(deviceOrder.getPayState())) {
            throw new LogicException("设备订单已撤销");
        }

        if(EPayType.WXPay.index().equals(deviceOrder.getPayType())){
            WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
            if (payOrder == null) {
                throw new LogicException("未找到本地微信支付订单");
            }
            WXPayNormalPayService payService = payServiceFactory.getWXPayNormalPayService(payOrder.getAppId(), CDCZConstants.BusinessType);
            if (payService == null) {
                throw new LogicException("未找到微信支付服务");
            }
            return cancel(deviceOrder,payOrder,payService,networkService,operateInfo);
        }else if(EPayType.EWallet.index().equals(deviceOrder.getPayType())){
            return cancel(deviceOrder,payServiceFactory.getMemberWalletService(),networkService,operateInfo);
        }
        return -1;
    }

    private int cancel(CDCZOrder deviceOrder, WXPayOrder payOrder, WXPayNormalPayService payService, ICDCZNetworkService networkService, OperateInfo operateInfo) throws LogicException {
        if(EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                if (networkService != null) {
                    CDCZExecuteResult executeResult = networkService.closeCharge(deviceOrder.getChargeSocketSn(), deviceOrder.getSlotNum());
                    log.info("充电插座关闭充电返回：{{0:json}}", executeResult);
                } else {
                    throw new LogicException("未初始化设备IOT服务");
                }
            }

            Integer refundMoney = deviceOrder.getPayMoney();
            Integer logState = ELogState.Success.index();
            String errorMsg = null;

            if (refundMoney > 0) {
                if(noOperateTo(deviceOrder.getTradeNo(),EOrderOperateState.Cancelling.index())) {
                        try {
                            //触发退款
                            WXRefundOrder refundOrder = WXRefundOrderService.self(deviceOrder.getCreateDate()).createRefundOrder(payOrder, refundMoney, operateInfo.getOperateNote());
                            WXPayNormalRefundResponse externalResult = payService.applyRefundOrder(refundOrder);
                            if (externalResult != null) {
                                if(StringTools.isNotBlank(externalResult.getCode()) && StringTools.isNotBlank(externalResult.getMessage())){
                                    logState = ELogState.Fail.index();
                                    errorMsg = externalResult.getMessage();
                                }else if (EWXPayNormalRefundState.SUCCESS.name().equals(externalResult.getStatus())){
                                    log.info("{{0}}订单微信直接退款成功，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                                }else if(EWXPayNormalRefundState.CLOSED.name().equals(externalResult.getStatus()) ||
                                        EWXPayNormalRefundState.ABNORMAL.name().equals(externalResult.getStatus())) {
                                    logState = ELogState.Fail.index();
                                    errorMsg = "退款订单已关闭或异常";
                                    log.error("{{0}}订单微信退款失败，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                                }
                            } else {
                                logState = ELogState.Fail.index();
                                errorMsg = "微信退款失败，无响应";
                                log.error("{{0}}订单微信退款失败，无返回信息", payOrder.getTradeNo());
                            }
                        } catch (Exception e) {
                            logState = ELogState.Fail.index();
                            errorMsg = e.getMessage();
                            log.error(e.getMessage(), e);
                        } finally {
                            if(ELogState.Fail.index().equals(logState)){
                                faceOperateState(deviceOrder.getTradeNo(),EOrderOperateState.NoOperation.index());
                            }
                        }
                }else{
                    logState = ELogState.Fail.index();
                    errorMsg = "撤销时锁定订单失败";
                }

                //记录日志
                CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, logState, errorMsg);
                if (ELogState.Success.index().equals(logState)) {
                    pullSlotInstantLog(deviceOrder);
                    return 1;
                }
            } else {
                Conditions conditions = new Conditions(CDCZOrder.class);
                conditions.and().is("tradeNo", deviceOrder.getTradeNo());
                conditions.and().is("operateState", deviceOrder.getOperateState());
                conditions.and().is("state", deviceOrder.getState());

                CDCZOrder updateEntity = new CDCZOrder();
                updateEntity.setTradeNo(deviceOrder.getTradeNo());
                updateEntity.setPayMoney(0);
                updateEntity.setPayState(CDCZOrderEnum.PayState.Cancel.index());
                //非终结状态，则修改为失败状态
                if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                    updateEntity.setState(CDCZOrderEnum.State.Close.index());
                } else if (CDCZOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                        || CDCZOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                    updateEntity.setState(CDCZOrderEnum.State.Fail.index());
                }
                if (CDCZOrderEnum.StopMode.Unknown.index().equals(deviceOrder.getStopMode())) {
                    updateEntity.setStopMode(CDCZOrderEnum.StopMode.ForceStop.index());
                }
                updateEntity.setCancelDate(new Date());
                if(deviceOrder.getFinishDate() == null){
                    updateEntity.setFinishDate(new Date());     //未完成时撤销
                }

                try {
                    if (dao.updateNotNull(updateEntity) <= 0) {
                        logState = ELogState.Fail.index();
                        errorMsg = "修改数据库失败";
                    }
                } catch (SQLException e) {
                    logState = ELogState.Fail.index();
                    errorMsg = e.getMessage();
                    log.error(e.getMessage(), e);
                }

                //记录日志
                CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, logState, errorMsg);
                if (ELogState.Success.index().equals(logState)) {
                    pullSlotInstantLog(deviceOrder);
                    return 2;
                }
            }
        }
        return -1;
    }

    private int cancel(CDCZOrder deviceOrder,IMemberWalletService memberWalletService, ICDCZNetworkService networkService, OperateInfo operateInfo)throws LogicException {
        if(EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                if (networkService != null) {
                    CDCZExecuteResult executeResult = networkService.closeCharge(deviceOrder.getChargeSocketSn(), deviceOrder.getSlotNum());
                    log.info("充电插座关闭充电返回：{{0:json}}", executeResult);
                } else {
                    throw new LogicException("未初始化设备IOT服务");
                }
            }

            Long refundMoney = deviceOrder.getWalletMoney();
            Integer operateState = ELogState.Success.index();
            String errorMsg = null;

            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("operateState",EOrderOperateState.NoOperation.index());
            conditions.and().is("state", deviceOrder.getState());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setWalletMoney(0L);
            updateEntity.setPayState(CDCZOrderEnum.PayState.Cancel.index());
            updateEntity.setCancelDate(new Date());
            if(deviceOrder.getFinishDate() == null){
                updateEntity.setFinishDate(new Date());     //未完成时撤销
            }

            //非终结状态，则修改为失败状态
            if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                updateEntity.setState(CDCZOrderEnum.State.Close.index());
            } else if (CDCZOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                    || CDCZOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                updateEntity.setState(CDCZOrderEnum.State.Fail.index());
            }
            if (CDCZOrderEnum.StopMode.Unknown.index().equals(deviceOrder.getStopMode())) {
                updateEntity.setStopMode(CDCZOrderEnum.StopMode.ForceStop.index());
            }

            JdbcSession.begin();
            try {
                if (dao.updateNotNull(updateEntity,conditions) > 0) {
                    if (refundMoney > 0) {
                        operateInfo.setOperateNote(deviceOrder.getTradeNo() + "订单撤销");
                        if (memberWalletService.addMoney(deviceOrder.getMemberId(), refundMoney, operateInfo)) {
                            JdbcSession.commit();
                        } else {
                            operateState = ELogState.Fail.index();
                            errorMsg = "新增会员钱包余额失败";
                        }
                    } else {
                        JdbcSession.commit();
                    }
                }else{
                    operateState = ELogState.Fail.index();
                    errorMsg = "修改数据库失败";
                }
            } catch (SQLException e) {
                operateState = ELogState.Fail.index();
                errorMsg = e.getMessage();
                log.error(e.getMessage(), e);
            } finally {
                JdbcSession.end();
            }

            //记录日志
            CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
            if (ELogState.Success.index().equals(operateState)) {
                pullSlotInstantLog(deviceOrder);
                return 2;
            }
        }
        return -1;
    }

    public int finish(CDCZOrder deviceOrder, Integer payMoney, IPayServiceFactory payServiceFactory,ICDCZNetworkService networkService,OperateInfo operateInfo) throws LogicException {
        if (CDCZOrderEnum.State.Finish.index().equals(deviceOrder.getState())) {
            throw new LogicException("设备订单已完成");
        }

        if(EPayType.WXPay.index().equals(deviceOrder.getPayType())){
            WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
            if (payOrder == null) {
                throw new LogicException("未找到本地微信支付订单");
            }
            WXPayNormalPayService payService = payServiceFactory.getWXPayNormalPayService(payOrder.getAppId(), CDCZConstants.BusinessType);
            if (payService == null) {
                throw new LogicException("未找到微信支付服务");
            }
            return finish(deviceOrder,payOrder,payMoney,payService,networkService,operateInfo);
        }else if(EPayType.EWallet.index().equals(deviceOrder.getPayType())){
            Long tempMoney = NumberTools.changeMoneyLi(NumberTools.changeMoney(payMoney));
            return finish(deviceOrder,tempMoney,payServiceFactory.getMemberWalletService(),networkService,operateInfo);
        }

        return -1;
    }

    private int finish(CDCZOrder deviceOrder, WXPayOrder payOrder, Integer payMoney, WXPayNormalPayService payService, ICDCZNetworkService networkService, OperateInfo operateInfo) throws LogicException {
        if(EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                if (networkService != null) {
                    CDCZExecuteResult executeResult = networkService.closeCharge(deviceOrder.getChargeSocketSn(), deviceOrder.getSlotNum());
                    log.info("充电插座关闭充电返回：{{0:json}}", executeResult);
                } else {
                    throw new LogicException("未初始化设备IOT服务");
                }
            }

            Integer refundMoney = 0;
            if (payOrder.getPayMoney() < payMoney) {
                throw new LogicException("客户支付金额小于结算金额，订单无法完成");
            } else if (payOrder.getPayMoney() > payMoney) {
                //单位转化，厘变分
                refundMoney = payOrder.getPayMoney() - payMoney;
            }

            Integer logState = ELogState.Success.index();
            String errorMsg = null;

            if (refundMoney > 0) {
                if (noOperateTo(deviceOrder.getTradeNo(), EOrderOperateState.Finishing.index())) {
                    //触发退款
                    WXRefundOrder refundOrder = WXRefundOrderService.self(deviceOrder.getCreateDate()).createRefundOrder(payOrder, refundMoney, operateInfo.getOperateNote());
                    WXPayNormalRefundResponse externalResult = payService.applyRefundOrder(refundOrder);
                    if (externalResult != null) {
                        if(StringTools.isNotBlank(externalResult.getCode()) && StringTools.isNotBlank(externalResult.getMessage())){
                            logState = ELogState.Fail.index();
                            errorMsg = externalResult.getMessage();
                        }else if (EWXPayNormalRefundState.SUCCESS.name().equals(externalResult.getStatus())){
                            log.info("{{0}}订单微信直接退款成功，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                        }else if(EWXPayNormalRefundState.CLOSED.name().equals(externalResult.getStatus()) ||
                                EWXPayNormalRefundState.ABNORMAL.name().equals(externalResult.getStatus())) {
                            logState = ELogState.Fail.index();
                            errorMsg = "退款订单已关闭或异常";
                            log.error("{{0}}订单微信退款失败，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                        }
                    } else {
                        logState = ELogState.Fail.index();
                        errorMsg = "微信退款失败，无响应";
                        log.error("{{0}}订单微信退款失败，无返回信息", payOrder.getTradeNo());
                    }

                    if (ELogState.Fail.index().equals(logState)) {
                        faceOperateState(deviceOrder.getTradeNo(), EOrderOperateState.NoOperation.index());
                    }
                } else {
                    logState = ELogState.Fail.index();
                    errorMsg = "完成时锁定订单失败";
                }

                //记录日志
                CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, logState, errorMsg);
                if (ELogState.Success.index().equals(logState)) {
                    pullSlotInstantLog(deviceOrder);
                    return 1;
                }
            } else {
                //支付金额不变，只修改订单状态
                Conditions conditions = new Conditions(CDCZOrder.class);
                conditions.and().is("tradeNo", deviceOrder.getTradeNo());
                conditions.and().is("operateState", deviceOrder.getOperateState());
                conditions.and().is("state", deviceOrder.getState());

                CDCZOrder updateEntity = new CDCZOrder();
                updateEntity.setTradeNo(deviceOrder.getTradeNo());
                if (CDCZOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                        || CDCZOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                    updateEntity.setState(CDCZOrderEnum.State.Close.index());
                } else if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                    updateEntity.setState(CDCZOrderEnum.State.Finish.index());
                }
                if (CDCZOrderEnum.StopMode.Unknown.index().equals(deviceOrder.getStopMode())) {
                    updateEntity.setStopMode(CDCZOrderEnum.StopMode.ForceStop.index());
                }
                updateEntity.setFinishDate(new Date());

                try {
                    if (dao.updateNotNull(updateEntity) <= 0) {
                        logState = ELogState.Fail.index();
                        errorMsg = "修改数据库失败";
                    }
                } catch (SQLException e) {
                    logState = ELogState.Fail.index();
                    errorMsg = e.getMessage();
                    log.error(e.getMessage(), e);
                }

                //记录日志
                CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, logState, errorMsg);
                if (ELogState.Success.index().equals(logState)) {
                    pullSlotInstantLog(deviceOrder);
                    return 2;
                }
            }
        }
        return -1;
    }

    private int finish(CDCZOrder deviceOrder, Long walletMoney, IMemberWalletService memberWalletService,ICDCZNetworkService networkService,OperateInfo operateInfo) throws LogicException {
        if(EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                if (networkService != null) {
                    CDCZExecuteResult executeResult = networkService.closeCharge(deviceOrder.getChargeSocketSn(), deviceOrder.getSlotNum());
                    log.info("充电插座关闭充电返回：{{0:json}}", executeResult);
                } else {
                    throw new LogicException("未初始化设备IOT服务");
                }
            }

            Long refundMoney = 0L;
            if (deviceOrder.getWalletMoney() < walletMoney) {
                throw new LogicException("客户支付金额小于结算金额，订单无法完成");
            } else if (deviceOrder.getWalletMoney() > walletMoney) {
                refundMoney = deviceOrder.getWalletMoney() - walletMoney;
            }

            Integer operateState = ELogState.Success.index();
            String errorMsg = null;

            //支付金额不变，只修改订单状态
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("operateState", deviceOrder.getOperateState());
            conditions.and().is("state", deviceOrder.getState());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setTradeNo(deviceOrder.getTradeNo());
            if (CDCZOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                    || CDCZOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                updateEntity.setState(CDCZOrderEnum.State.Close.index());
            } else if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                updateEntity.setState(CDCZOrderEnum.State.Finish.index());
            }
            if (CDCZOrderEnum.StopMode.Unknown.index().equals(deviceOrder.getStopMode())) {
                updateEntity.setStopMode(CDCZOrderEnum.StopMode.ForceStop.index());
            }
            updateEntity.setFinishDate(new Date());

            if(refundMoney > 0){
                JdbcSession.begin();
                try {
                    operateInfo.setOperateNote(deviceOrder.getTradeNo() + "订单完成后剩余退款");
                    if(memberWalletService.addMoney(deviceOrder.getMemberId(),refundMoney,operateInfo)){
                        updateEntity.setWalletMoney(walletMoney);
                        if (dao.updateNotNull(updateEntity) > 0) {
                            JdbcSession.commit();
                        }else{
                            operateState = ELogState.Fail.index();
                            errorMsg = "修改数据库失败";
                        }
                    }else{
                        operateState = ELogState.Fail.index();
                        errorMsg = "修改会员余额失败";
                    }
                } catch (SQLException e) {
                    operateState = ELogState.Fail.index();
                    errorMsg = e.getMessage();
                    log.error(e.getMessage(), e);
                } finally {
                    JdbcSession.end();
                }

                //记录日志
                CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
                if (ELogState.Success.index().equals(operateState)) {
                    pullSlotInstantLog(deviceOrder);
                    return 2;
                }
            }else{
                try {
                    if (dao.updateNotNull(updateEntity) <= 0) {
                        operateState = ELogState.Fail.index();
                        errorMsg = "修改数据库失败";
                    }
                } catch (SQLException e) {
                    operateState = ELogState.Fail.index();
                    errorMsg = e.getMessage();
                    log.error(e.getMessage(), e);
                }

                //记录日志
                CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
                if (ELogState.Success.index().equals(operateState)) {
                    pullSlotInstantLog(deviceOrder);
                    return 2;
                }
            }
        }
        return -1;
    }

    public boolean timesFillToFinish(CDCZOrder deviceOrder, Long payMoney,ICDCZNetworkService networkService, OperateInfo operateInfo) throws LogicException {
       if(EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
           if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
               if (networkService != null) {
                   CDCZExecuteResult executeResult = networkService.closeCharge(deviceOrder.getChargeSocketSn(), deviceOrder.getSlotNum());
                   log.info("充电插座关闭充电返回：{{0:json}}", executeResult);
               } else {
                   throw new LogicException("未初始化设备IOT服务");
               }
           }else {
               if (CDCZOrderEnum.State.Finish.index().equals(deviceOrder.getState()) || CDCZOrderEnum.State.Close.index().equals(deviceOrder.getState())) {
                   log.error("时间到停触发订单完成，但{{0}}订单已结束，当前订单状态：{{1}}，停止状态：{{2}}", deviceOrder.getTradeNo(), deviceOrder.getStateName(), deviceOrder.getStopModeName());
                   return true;
               }
               operateInfo.setOperateNote(operateInfo.getOperateNote() + "(设备订单状态异常，当前状态："+deviceOrder.getStateName()+")");
           }

           Long walletMoney = null;
           if(deviceOrder.getLastDeductionDate() != null && payMoney != null){
               int times = 15;     //15分钟扣费一次
               Long minute = DateTools.differenceMinute(deviceOrder.getLastDeductionDate(), deviceOrder.getEndDate());
               if(minute >= times){
                   deviceOrder = getByTradeNo(deviceOrder.getTradeNo());
                   minute = DateTools.differenceMinute(deviceOrder.getLastDeductionDate(), deviceOrder.getEndDate());
               }
               if(minute > 0) {
                   Long count = minute / times;
                   if(minute % times > 0){
                       count = count + 1;
                   }
                   walletMoney = NumberTools.multiply(NumberTools.divide(payMoney, 4, 0), count);
               }
           }

           Long useTimes = DateTools.differenceMinute(deviceOrder.getStartDate(),deviceOrder.getEndDate());
           Integer operateState = ELogState.Success.index();
           String errorMsg = null;

           if(walletMoney > 0){
               Conditions conditions = new Conditions(CDCZOrder.class);
               conditions.and().is("tradeNo", deviceOrder.getTradeNo());
               conditions.and().is("operateState", EOrderOperateState.NoOperation.index());
               conditions.and().is("lastDeductionDate",deviceOrder.getLastDeductionDate());
               conditions.and().is("state", deviceOrder.getState());

               CDCZOrder updateEntity = new CDCZOrder();
               updateEntity.setTradeNo(deviceOrder.getTradeNo());
               updateEntity.setStopMode(CDCZOrderEnum.StopMode.TimesFillStop.index());
               updateEntity.setMoney(walletMoney);
               updateEntity.setWalletMoney(walletMoney);
               updateEntity.setUseTimes(useTimes.intValue());


               if (CDCZOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                       || CDCZOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                   updateEntity.setState(CDCZOrderEnum.State.Close.index());
               } else if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                   updateEntity.setState(CDCZOrderEnum.State.Finish.index());
               }
               updateEntity.setFinishDate(new Date());

               try {
                   if (dao.updateNotNullAndInc(updateEntity,conditions,"walletMoney","money") <= 0) {
                       operateState = ELogState.Fail.index();
                       errorMsg = "修改数据库失败";
                   }
               } catch (SQLException e) {
                   operateState = ELogState.Fail.index();
                   errorMsg = e.getMessage();
                   log.error(e.getMessage(), e);
               }

               //添加订单日志
               OperateInfo tempOperateInfo = ClassTools.copy(new OperateInfo(),operateInfo);
               tempOperateInfo.setOperateNote("订单结束，最后一次扣费" + NumberTools.getMoneyLiStr(walletMoney) + "元，当前功率：" + deviceOrder.getMaxUsePower()
                       + "，每小时收费：" + NumberTools.getMoneyLiStr(payMoney) + "元");
               CDCZOrderChargeLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, tempOperateInfo, operateState, errorMsg);
           }else {
               Conditions conditions = new Conditions(CDCZOrder.class);
               conditions.and().is("tradeNo", deviceOrder.getTradeNo());
               conditions.and().is("operateState", EOrderOperateState.NoOperation.index());
               conditions.and().is("state", deviceOrder.getState());

               CDCZOrder updateEntity = new CDCZOrder();
               updateEntity.setStopMode(CDCZOrderEnum.StopMode.TimesFillStop.index());
               updateEntity.setUseTimes(useTimes.intValue());

               if (CDCZOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                       || CDCZOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                   updateEntity.setState(CDCZOrderEnum.State.Close.index());
               } else if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                   updateEntity.setState(CDCZOrderEnum.State.Finish.index());
               }
               updateEntity.setFinishDate(new Date());

               try {
                   if (dao.updateNotNull(updateEntity,conditions) <= 0) {
                       operateState = ELogState.Fail.index();
                       errorMsg = "修改数据库失败";
                   }
               } catch (SQLException e) {
                   operateState = ELogState.Fail.index();
                   errorMsg = e.getMessage();
                   log.error(e.getMessage(), e);
               }
           }

           //记录日志
           CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
           if (ELogState.Success.index().equals(operateState)) {
               pullSlotInstantLog(deviceOrder);
               return true;
           }
       }
       return false;
    }

    public boolean noMoneyToFinish(CDCZOrder deviceOrder, ICDCZNetworkService networkService, OperateInfo operateInfo) throws LogicException {
        if(EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                if (networkService != null) {
                    CDCZExecuteResult executeResult = networkService.closeCharge(deviceOrder.getChargeSocketSn(), deviceOrder.getSlotNum());
                    log.info("充电插座关闭充电返回：{{0:json}}", executeResult);
                } else {
                    throw new LogicException("未初始化设备IOT服务");
                }
            }

            if(!CDCZOrderEnum.StopMode.Unknown.index().equals(deviceOrder.getStopMode())) {
                return true;
            }

            Integer operateState = ELogState.Success.index();
            String errorMsg = null;

            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("operateState", EOrderOperateState.NoOperation.index());
            conditions.and().is("state", deviceOrder.getState());

            CDCZOrder updateEntity = new CDCZOrder();
            updateEntity.setTradeNo(deviceOrder.getTradeNo());
            updateEntity.setStopMode(CDCZOrderEnum.StopMode.ForceStop.index());

            if (CDCZOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                    || CDCZOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                updateEntity.setState(CDCZOrderEnum.State.Close.index());
            } else if (CDCZOrderEnum.State.Working.index().equals(deviceOrder.getState())) {
                updateEntity.setState(CDCZOrderEnum.State.Finish.index());
            }
            updateEntity.setFinishDate(new Date());

            try {
                if(dao.updateNotNull(updateEntity,conditions) <= 0){
                    operateState = ELogState.Fail.index();
                    errorMsg = "修改数据库失败";
                }
            } catch (SQLException e) {
                operateState = ELogState.Fail.index();
                errorMsg = e.getMessage();
                log.error(e.getMessage(), e);
            }

            //记录日志
            CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
            if (ELogState.Success.index().equals(operateState)) {
                pullSlotInstantLog(deviceOrder);
                return true;
            }
        }
        return false;
    }

    /**
     * 拉取卡槽瞬时数据
     * @param deviceOrder
     */
    private void pullSlotInstantLog(CDCZOrder deviceOrder){
        //拉取设备瞬时数据日志
        if(deviceOrder.getStartDate() != null && deviceOrder.getEndDate() != null) {
            Date startDate = deviceOrder.getStartDate();
            Date endDate = DateUtils.addMinutes(deviceOrder.getEndDate(), 10); //多10分钟的日志数据

            List<CDCZSlotInstantLog> instantLogList = CDCZSlotInstantLogService.self()
                    .findByKeysAndDate(deviceOrder.getChargeSocketSn(), deviceOrder.getSlotNum(), startDate, endDate);
            if (instantLogList != null && instantLogList.size() > 0) {
                CDCZOrderDeviceLogContent content = new CDCZOrderDeviceLogContent();
                for (CDCZSlotInstantLog instantLog : instantLogList) {
                    CDCZOrderDeviceLogContent.LogItem item = new CDCZOrderDeviceLogContent.LogItem();
                    item.setDate(instantLog.getCreateDate());
                    item.setInstantPower(instantLog.getInstantPower());
                    item.setInstantCurrent(instantLog.getInstantCurrent());
                    content.getItems().add(item);
                }

                CDCZOrderDeviceLog deviceLog = new CDCZOrderDeviceLog();
                deviceLog.setTradeNo(deviceOrder.getTradeNo());
                deviceLog.setChargeSocketSn(deviceOrder.getChargeSocketSn());
                deviceLog.setSlotNum(deviceOrder.getSlotNum());
                deviceLog.setContent(JsonTools.toJson(content));
                deviceLog.setCreateDate(deviceOrder.getCreateDate());
                if (!CDCZOrderDeviceLogService.self(deviceOrder.getCreateDate()).save(deviceLog)) {
                    log.error("充电插座{{0}}订单完成充电后，保存拉取的设备瞬时数据日志失败", deviceOrder.getTradeNo());
                }
            } else {
                log.error("充电插座{{0}}订单完成充电后，未找到{{1}}设备{{2}}号卡槽的瞬时数据日志", deviceOrder.getTradeNo(), deviceOrder.getChargeSocketSn(), deviceOrder.getSlotNum());
            }
        }
    }

    public boolean faceOperateState(String tradeNo,Integer operateState){
        if(StringTools.isNotBlank(tradeNo) && operateState != null){
            CDCZOrder deviceOrder = new CDCZOrder();
            deviceOrder.setTradeNo(tradeNo);
            deviceOrder.setOperateState(operateState);

            try {
                return dao.updateNotNull(deviceOrder) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean noOperateTo(String tradeNo,Integer operateState){
        if(StringTools.isNotBlank(tradeNo) && operateState != null){
            Conditions conditions = new Conditions(CDCZOrder.class);
            conditions.and().is("tradeNo",tradeNo);
            conditions.and().is("operateState",EOrderOperateState.NoOperation.index());

            CDCZOrder deviceOrder = new CDCZOrder();
            deviceOrder.setOperateState(operateState);

            try {
                return dao.updateNotNull(deviceOrder,conditions) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }
}
